/* Compile me with:  jflex Specification.lex  */
package ex2;

%%

%class Scanner

%type Token

%{
Token tok(String tag) {
	return new Token(yyline, yycolumn, tag, yytext());
}

Token err(String tag) {
	return new TokenErr(yyline, yycolumn, tag, yytext());
}
%}

%column
%line

ID = [a-z][a-zA-Z0-9_]*
CLASS_ID = [A-Z][a-zA-Z0-9_]*
INTEGER = [1-9][0-9]*|0
STRING = (\".*\\\".*\")|(\".*\\\\.*\")|(\".*\\n.*\")|(\".*\\t.*\")|(\"[^\\\"\t]*\")
OPERATORS = "<="|">="|"=="|"!="|"&&"|"||"|"+"|"-"|"/"|"*"|"!"|"%"
VALID_CHARS = ";"|"{"|"}"|"["|"]"|"("|")"|","|"="|">"|"<"|"."
RESERVED_WORDS = class|extends|static|void|int|boolean|string|return|if|else|while|break|continue|this|new|length|true|false|null
WHITESPACE= [ \t\n]
COMMENTS = {TraditionalComment} | {EndOfLineComment}| {DocumentationComment}

LINE_START_ERR = _
STRING_ERR = [\"]
INVALID_CHAR_ERR = .
COMMENT_ERR = \/\*
NUM_ERROR = 0[0-9]+

EndOfLineComment = \/\/[^\r\n]*[\r|\n|\r\n]
TraditionalComment = \/\*[^\*]*\*\/
DocumentationComment = \/\*([^\*]|\*+[^\/])*\*\/

%%

{WHITESPACE}        { /* nothing; skip */ }
{COMMENTS}          { /* nothing; skip */}
{RESERVED_WORDS}    { return tok(yytext()); }
{CLASS_ID}          { return tok("CLASS_ID"); }
{NUM_ERROR}         { return err("lexical error; numbers should not have leading zeros");}
{INTEGER}           { return tok("INTEGER"); }
{STRING}            { return tok("STRING"); }
{ID}                { return tok("ID"); }
{COMMENT_ERR}       { return err("lexical error; unterminated comment");}
{OPERATORS}         { return tok(yytext());}
{VALID_CHARS}       { return tok(yytext());}
{STRING_ERR}        { return err("lexical error; malformed string literal");}
{NUM_ERROR}         { return err("lexical error; numbers should not have leading zeros");}
{LINE_START_ERR}    { return err("lexical error; an identifier cannot start with '"+yytext()+"'");}
{INVALID_CHAR_ERR}  { return err("lexical error; invalid character '" + yytext() +"'");}


